﻿//============================================================
//write by bxl at 2021-05-29 14:47:49
//============================================================



using System.Collections.Generic;
using System;
using BCService.Utils;
using BCCommon;
using BCData.TMS.Fence;
using BCDto.TMS.Fence;
using BCEntity.TMS.Fence;
using BCDto.Sim.Admin.Admin;
using BCMongoData.TMS.Fence;
using BCMongoEntity.TMS.Fence;
using BCCommon.Extensions;
using BCCommon.Enums.TMS;
using BCData.Common.Area;
using BCDto.TMS.SpecificServiceType;
using BCService.Common.Area;
using BCService.TMS.WorkingCompany;
using BCData.TMS.WorkingCompany;
using BCEntity.Common.EntityNameConst;
using BCDto.TMS.WorkingCompany;
using NPOI.SS.Formula.Functions;
using System.Security.Cryptography.X509Certificates;

namespace BCService.TMS.Fence
{
    public class FenceService : IFenceService
    {
        #region var
        private readonly IDatabaseContext databaseContext;
        private IFenceData fenceData;
        private IFenceMongoData fenceMongoData;
        private IRedisService redisService;
        private readonly IZoneService zoneService;
        private IWorkingCompanyData workingCompanydata;


        private readonly string key = string.Format("{0}", EntityNameConst.FenceEntity);
        #endregion 

        #region 构造函数
        public FenceService(
            IZoneService zoneService,
            IDatabaseContext databaseContext,
            IFenceData fenceData,
            IFenceMongoData fenceMongoData,
            IRedisService redisService,
            IWorkingCompanyData workingCompanyData)
        {
            this.zoneService = zoneService;
            this.databaseContext = databaseContext;
            this.fenceData = fenceData;
            this.fenceMongoData = fenceMongoData;
            this.redisService = redisService;
            this.workingCompanydata = workingCompanyData;
        }
        #endregion

        #region Add
        /// <summary>
        /// 添加新电子围栏纪录
        /// </summary>
        /// <param name="admin"></param>
        /// <param name="fenceRequestDto"></param>
        /// <returns></returns>
        public FenceDto Add(FenceRequestDto fenceRequestDto, AdminDto admin)
        {
            FenceMongoEntity fenceMongoEntity = AddToMongoDB(fenceRequestDto, admin);
            var fenceEntity = fenceMongoEntity.As<FenceEntity>();
            fenceEntity.MongoId = fenceMongoEntity.Id;
            fenceEntity.CoordinateList = JsonExtensions.ObjectToJson(fenceMongoEntity.CoordinateList);

            return fenceData.InsertAsync(fenceEntity).GetAwaiter().GetResult().As<FenceDto>();
        }
        //添加mongo库
        private FenceMongoEntity AddToMongoDB(FenceRequestDto fenceRequestDto, AdminDto admin)
        {
            FenceMongoEntity fenceMongoEntity = fenceRequestDto.As<FenceMongoEntity>();
            fenceMongoEntity.Id = BCCommon.GuidGenerate.NewGuid();
            fenceMongoEntity.CtrlCompanyId = admin.CompanyId;
            fenceMongoEntity.CtrlCompanyName = admin.CompanyName;
            fenceMongoEntity.CoordinateList = fenceRequestDto.PointList;
            fenceMongoEntity.CreateTime = MongoDBDateTime.UtcNow;

            GetPublicProperty(fenceMongoEntity, admin);
            return fenceMongoData.AddNew(fenceMongoEntity, fenceRequestDto.GpsMapType);
        }
        //获取公共属性
        private void GetPublicProperty(FenceMongoEntity fenceMongoEntity, AdminDto admin)
        {
            var zoneEntity = this.zoneService.GetFromZoneEntity(fenceMongoEntity.CountyCode);
            if (zoneEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("区县编码不存在!");
            }
            var workCompanyEntity = workingCompanydata.GetEntity(fenceMongoEntity.WorkCompanyId).GetAwaiter().GetResult() ?? throw new ArgumentException("劳务公司不存在!");

            fenceMongoEntity.ProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
            fenceMongoEntity.ProvinceName = zoneEntity.provinceEntity.ProvinceName;
            fenceMongoEntity.CityCode = zoneEntity.cityEntity.CityCode;
            fenceMongoEntity.CityName = zoneEntity.cityEntity.CityName;
            fenceMongoEntity.CountyName = zoneEntity.countyEntity.CountyName;

            fenceMongoEntity.WorkCompanyName = workCompanyEntity.WorkingCompanyName;

            fenceMongoEntity.EditorId = admin.AdminId;
            fenceMongoEntity.Editor = admin.FullName;
            fenceMongoEntity.EditTime = BCCommon.MongoDBDateTime.UtcNow;
        }
        #endregion

        #region update
        /// <summary>
        /// 修改电子围栏记录
        /// </summary>
        /// <param name="admin"></param>
        /// <param name="fencePutDto"></param>
        /// <returns></returns>
        public FenceDto Update(FencePutDto fencePutDto, AdminDto admin)
        {
            FenceMongoEntity fenceMongoEntity = UpdateMongoDB(fencePutDto, admin);
            var fenceEntity = fenceMongoEntity.As<FenceEntity>();
            fenceEntity.FenceId = fencePutDto.FenceId;
            fenceEntity.MongoId = fenceMongoEntity.Id;
            fenceEntity.CoordinateList = JsonExtensions.ObjectToJson(fenceMongoEntity.CoordinateList);

            var a = fenceData.UpdateAsync(fenceEntity).GetAwaiter().GetResult().As<FenceDto>();
            string cacheKey = this.redisService.GetKey(key, fencePutDto.FenceId);
            string cacheCountyKey = this.redisService.GetKey(key, fencePutDto.WorkCompanyId, fencePutDto.CountyCode);
            this.redisService.DeleteAsync(cacheKey);
            this.redisService.DeleteAsync(cacheCountyKey);
            return a;
        }

        private FenceMongoEntity UpdateMongoDB(FencePutDto fencePutDto, AdminDto admin)
        {
            var old = GetById(fencePutDto.FenceId) ?? throw new ArgumentException("找不到对应的围栏!");
            var fenceMongoEntity = fencePutDto.As<FenceMongoEntity>();
            fenceMongoEntity.Id = old.MongoId;
            fenceMongoEntity.CtrlCompanyId = old.CtrlCompanyId;
            fenceMongoEntity.CtrlCompanyName = old.CtrlCompanyName;

            fenceMongoEntity.CoordinateList = fencePutDto.PointList;
            GetPublicProperty(fenceMongoEntity, admin);
            return fenceMongoData.Update(fenceMongoEntity, fencePutDto.GpsMapType);

        }
        #endregion

        #region Delete
        /// <summary>
        /// 删除电子围栏记录
        /// </summary>
        /// <param name="fenceId"></param>
        /// <returns></returns>
        public void Delete(long fenceId)
        {
            var entity = GetById(fenceId);
            if (entity == null)
                return;

            string cacheKey = this.redisService.GetKey(key, fenceId);
            string cacheCountyKey = this.redisService.GetKey(key, entity.WorkCompanyId, entity.CountyCode);
            this.redisService.DeleteAsync(cacheKey);
            this.redisService.DeleteAsync(cacheCountyKey);

            fenceMongoData.Delete(entity.MongoId);
            fenceData.DeleteAsync(fenceId).GetAwaiter().GetResult();
        }
        #endregion

        #region GetByFenceId
        /// <summary>
        /// 获取电子围栏记录
        /// </summary>
        /// <param name="fenceId"></param>
        /// <returns></returns>
        public FenceDto GetById(long fenceId)
        {
            string cacheKey = this.redisService.GetKey(key, fenceId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var a = fenceData.GetEntityAsync(fenceId).GetAwaiter().GetResult();
                return a.As<FenceDto>();

            }, TimeSpan.FromDays(1));
            return result.As<FenceDto>();
        }
        #endregion

        #region GetList  获取电子围栏记录--[分页]
        public PageableList<FenceDto> GetList(AdminDto admin, string workingCompanyName, string provinceCode, string cityCode, string countyCode, string fenceName, bool? isEnable, int pageIndex, int pageSize)
        {
            int fCount = 0;
            IEnumerable<FenceEntity> fList;
            string cacheKey = this.redisService.GetKey(key, admin.CompanyId, workingCompanyName, provinceCode, cityCode, countyCode, fenceName, isEnable, pageIndex, pageSize);

            var result = this.redisService.TryGet(cacheKey, () =>
            {

                (fList, fCount) = fenceData.GetListAsync(admin.CompanyId, workingCompanyName, provinceCode, cityCode, countyCode, fenceName, isEnable, pageIndex, pageSize).GetAwaiter().GetResult();

                return new PageableList<FenceDto>()
                {
                    Count = fCount,
                    Items = fList.As<IEnumerable<FenceDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now,
                };
            }, TimeSpan.FromMinutes(30));

            return result;
        }
        #endregion

        #region   获取电子围栏记录
        public List<FenceDto> GetOnlyList(AdminDto admin, string workingCompanyName, string provinceCode, string cityCode, string countyCode, string fenceName, bool? isEnable)
        {
            string cacheKey = this.redisService.GetKey(key, admin.CompanyId, workingCompanyName, provinceCode, cityCode, countyCode, fenceName, isEnable);

            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return fenceData.GetOnlyListAsync(admin.CompanyId, workingCompanyName, provinceCode, cityCode, countyCode, fenceName, isEnable).GetAwaiter().GetResult().As<List<FenceDto>>();
            }, TimeSpan.FromMinutes(30));

            return result;
        }
        #endregion

        #region 获取目标点所在的围栏列表
        public List<FenceDto> GetIntoFenceList(double lng, double lat, string ProvinceCode, string CityCode, string CountyCode, GpsMapType gpsMapType)
        {
            var fenceList = fenceMongoData.GetIntoFenceList(lng, lat, ProvinceCode, CityCode, CountyCode, gpsMapType);
            if (fenceList != null && fenceList.Count > 0)
            {
                List<FenceDto> listRst = new List<FenceDto>();
                foreach (var item in fenceList)
                {
                    listRst.Add(GetByMongoId(item.Id));
                }
                return listRst;

            }
            else
                return null;
        }

        //根据MongoId获取记录
        private FenceDto GetByMongoId(string id)
        {
            return fenceData.GetByMongoIdAsync(id).GetAwaiter().GetResult().As<FenceDto>();
        }
        #endregion

        #region 获取目标点是否在指定围栏内
        public bool IsIntoFence(long fenceId, double lng, double lat, GpsMapType gpsMapType)
        {
            var fenceDto = GetById(fenceId);
            if (fenceDto != null)
            {
                if (!string.IsNullOrWhiteSpace(fenceDto.MongoId))
                {
                    var fenceMongo = fenceMongoData.IntoFence(fenceDto.MongoId, lng, lat, gpsMapType);
                    if (fenceMongo != null)
                        return true;
                    else
                        return false;
                }
            }
            return false;
        }
        #endregion


        public FenceDto GetByWorkCompanyIdAndCountyCode(long workingCompanyId, string countyCode)
        {
            string cacheKey = this.redisService.GetKey(key, workingCompanyId, countyCode);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = fenceData.GetByWorkCompanyIdAndCountyCodeAsync(workingCompanyId, countyCode).GetAwaiter().GetResult();
                return data.As<FenceDto>();
            }, TimeSpan.FromDays(1));
            return result;
        }
    }
}